package com.unitd.frame.sso.common.shiro.impl;

import com.unitd.frame.sso.common.shiro.IShiroPermission;
import com.unitd.frame.sso.common.token.Token;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import java.util.List;

/**
 * @desc sso 信任票据域,继承子 shiro 的 AuthorizingRealm ,实现用户身份授权及验证处理
 * @filename SSOAuthRealm.java
 * @copyright www.unitd.com
 * @author Hudan
 * @version 1.0
 * @date 2016/10/14
 */
public class SSOAuthRealm extends AuthorizingRealm {

	private IShiroPermission shiroPermission;

	/**
	 * @desc 重新shiro的授权方法, 根据用户身份获取授权信息
	 * PrincipalCollection 用于聚合用户身份形成一个集合对象
	 * @param principals 用户身份集合对象
	 * @return
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		if (principals == null) {
			throw new AuthorizationException("PrincipalCollection方法参数不能为空.");
		}
		Token token = (Token) getAvailablePrincipal(principals);
		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
		List<String> permissions = shiroPermission.getPermissions(token);
		if (permissions != null) {
			authorizationInfo.addStringPermissions(permissions);
		}
		return authorizationInfo;
	}

	/**
	 * @desc 获取身份验证信息
	 * @param token 用户提交的身份、凭据信息
	 * AuthenticationToken用于收集用户提交的身份（如用户名）及凭据（如密码）等;
	 * AuthenticationInfo有两个作用：
	 *                 1、如果Realm是AuthenticatingRealm子类,则提供给AuthenticatingRealm内部使用的CredentialsMatcher进行凭据验证;（如果没有继承它需要在自己的Realm中自己实现验证）;
	 *                 2、提供给SecurityManager来创建Subject（提供身份信息）
	 * @return
	 * @throws AuthenticationException
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		return new SimpleAuthenticationInfo(token.getPrincipal(), token.getCredentials(), getName());
	}

	@Override
	public boolean supports(AuthenticationToken token) {
		return token != null && SSOAuthToken.class.isAssignableFrom(token.getClass());
	}

	@Override
	public Class<?> getAuthenticationTokenClass() {
		return SSOAuthToken.class;
	}

	public IShiroPermission getShiroPermission() {
		return shiroPermission;
	}

	public void setShiroPermission(IShiroPermission shiroPermission) {
		this.shiroPermission = shiroPermission;
	}
}